(function ($, _) {
    "use strict";
    var collections = {},
        clnTemplate = $("#collection-template").html(),

        $doc = $(document),
        $loading = $("#loading-bar"),
        $clnContainer = $("#collection-container"),
        $clnName = $("#cln-name"),
        $clnNumbers = $("#cln-numbers"),
        $clnSubmit = $("#cln-submit"),
        $clnFormat = $("#cln-format"),
        $clnAdd = $("#cln-add"),
        $curEditing = null,
        curEditingId = null,
        updateHandler = null;

    var msg = (function () {
        var el = $("#msg").hide(),
            timer = null,
            show = function (content, timeout) {
                if (timer != null) {
                    clearTimeout(timer);
                }
                el.clearQueue().hide().children(".content").text(content);
                el.show().css("opacity", 0).animate({ opacity: 1}, 400);

                if (timeout == undefined) {
                    timeout = 5000;
                }

                timer = setTimeout(hide, timeout);

            },
            hide = function () {
                el.clearQueue().fadeOut(300);
            };

        el.on("click", ".close", function () {
            hide();
        });

        return {
            show: show,
            hide: hide
        };
    }());

    // Initialize
    $doc.ajaxSend(function () {
        $loading.clearQueue().show();
    }).ajaxComplete(function () {
            $loading.hide();
        });


    // Load collection
    collections = (function () {
        $.getJSON('api/collection', function (json) {
            collections = {};
            _(json).each(function (cln) {
                $("<div class='collection-outer'/>").html(_.template(clnTemplate, cln))
                    .appendTo($clnContainer);

                // Caching collections
                collections[cln.id] = {
                    name: cln.name,
                    numbers: cln.numbers
                };
            });
        });
    }());

    // Edit collection event
    $clnContainer.on("click", "a.edit", function (e) {
        e.preventDefault();
        updateHandler = updateCollection;
        var self = $(this),
            cln = collections[self.data('id')];

        curEditingId = self.data('id');
        $curEditing = self.parent();
        $clnName.val(cln.name);
        $clnNumbers.val(cln.numbers.join(", "));
    });

    // Delete
    $clnContainer.on("click", "a.del", function (e) {
        e.preventDefault();
        var id = $(this).data('id'),
            $div = $(this).parent();
        if (confirm("Do you want to delete collection [" + collections[id].name + "] ?")) {
            $.ajax("api/collection", {
                type: 'DELETE',
                data: { id: id },
                success: function () {
                    $div.fadeOut(800, function () {
                        $(this).remove();
                    });
                    delete collections[id];
                }
            })
        }
    });

    // Update collection
    var updateCollection = function () {
        if (curEditingId == null) {
            alert("Please select collection to update!");
        } else {
            if ($clnName.val().trim() == "") {
                alert("Don't leave collection name empty");
                $clnName.focus();
            } else {
                $.ajax("api/collection", {
                    type: 'PUT',
                    data: {
                        id: curEditingId,
                        name: $clnName.val(),
                        numbers: getNumbers()
                    },
                    cache: false,
                    success: function (json) {
                        if (json.code != 0) {
                            alert("Update failed! Please try again!");
                        } else {
                            msg.show("Update collection successful!");
                            $(".name", $curEditing).text(json.data.name);
                            collections[curEditingId] = json.data;
                            curEditingId = null;
                        }
                    },
                    dataType: 'json'
                });
            }
        }
    };

    var addCollection = function () {
        if ($clnName.val().trim() == "") {
            alert("Don't leave collection name empty");
            $clnName.focus();
        } else {
            $.ajax("api/collection", {
                type: "POST",
                data: {
                    name: $clnName.val(),
                    numbers: getNumbers()
                },
                success: function (json) {
                    if (json.code != 0) {
                        alert("Add collection error, please try again!");
                    } else {
                        collections[json.data.id] = json.data;

                        var $e = $("<div class='collection-outer'/>").html(_.template(clnTemplate, json.data))
                            .appendTo($clnContainer).css("opacity", 0);
                        $clnContainer.scrollTop($clnContainer.height());
                        $e.animate({ opacity: 1}, 400);
                        msg.show("Add collection successful!");
                    }
                }
            })
        }
    };

    // Add collection
    $clnAdd.click(function (e) {
        e.preventDefault();
        curEditingId = null;
        updateHandler = addCollection;
        $clnName.val("new collection");
        $clnNumbers.val("");
    });

    $clnSubmit.click(function () {
        if (updateHandler == null) updateHandler = updateCollection;
        updateHandler();
    });

    // Collection-outer .name click --> add numbers to clnNumbers

    $clnContainer.on("click", ".collection-outer .name", function () {
        var id = $(this).next().data('id');
        $clnNumbers.val($clnNumbers.val() + " " + collections[id].numbers.join(", "));
    });

    var getNumbers = function () {
        var numberRegex = /\d{1,2}/g,
            numbers = [],
            r;
        while ((r = numberRegex.exec($clnNumbers.val())) != null) {
            var n = parseInt(r[0]);
            if (numbers.indexOf(n) < 0) {
                numbers.push(n);
            }
        }

        return numbers.sort();
    };

    $clnFormat.click(function () {
        $clnNumbers.val(getNumbers().join(", "));

        msg.show("Numbers formatted!", 3000);
    });

}(window.jQuery, window._));